package builder

import (
	"errors"
	"fmt"
	"strings"
	"sync"
	"yunj/pkg/yunj/core/builder/builderdto"
	"yunj/pkg/yunj/core/consts"
	"yunj/pkg/yunj/core/enum"
	"yunj/pkg/yunj/util"
)

// 处理树选择节点
// @Param nodes 节点
// @Param lastChecked 是否末级可选
// @Return activeNodeIdCommaStr 可选择的节点id逗号分割字符串
func HandleTreeCheckNodes(nodes []*builderdto.FormTreeCheckNode, lastChecked bool) (activeNodeIdCommaStr string, err error) {
	if nodes == nil || len(nodes) <= 0 {
		err = errors.New("节点 Nodes 未配置！")
		return
	}
	nodeIdIdx := map[any]int{} // 存储节点id和索引位置
	for i, node := range nodes {
		// 判断节点id
		if node.Id == nil {
			err = fmt.Errorf("节点 Nodes[%v].Id 不能为空", i)
			return
		}
		// hasSub 是否有子节点
		hasSub := false
		for _, _node := range nodes {
			if _node.Pid == node.Id {
				hasSub = true
				break
			}
		}
		nodes[i].HasSub = hasSub
		nodeIdIdx[node.Id] = i
	}
	// 完善full_name字段
	for _, node := range nodes {
		if node.FullName != "" {
			continue
		}
		node.FullName = getTreeCheckNodeFullName(node, nodeIdIdx, nodes)
	}
	// 存储可选节点id和索引位置
	activeNodeIdIdx := map[any]int{}
	for i, node := range nodes {
		// nocheck 是否不可选
		if node.Nocheck {
			continue
		}
		if lastChecked {
			// 最后一级可选
			node.Nocheck = node.HasSub
		} else {
			// 全部可选
			node.Nocheck = false
		}
		// 获取可选的节点id
		if !node.Nocheck && !node.Readonly {
			activeNodeIdIdx[node.Id] = i
		}
		nodes[i] = node
	}
	// 获取可选节点ids
	activeNodeIds := make([]string, 0, len(activeNodeIdIdx))
	var idStr string
	for id, idx := range activeNodeIdIdx {
		idStr, err = util.ToString(id)
		if err != nil {
			err = fmt.Errorf("节点 Nodes[%v] Id 不能转换为字符串", idx)
			return
		}
		activeNodeIds = append(activeNodeIds, idStr)
	}
	activeNodeIdCommaStr = strings.Join(activeNodeIds, ",")
	return
}

// 获取树选择节点的完整名称
func getTreeCheckNodeFullName(node *builderdto.FormTreeCheckNode, nodeIdIds map[any]int, nodes []*builderdto.FormTreeCheckNode) string {
	fullName := node.Name
	if parentNodeIdx, exists := nodeIdIds[node.Pid]; exists {
		if parentNode := nodes[parentNodeIdx]; parentNode != nil {
			fullName = getTreeCheckNodeFullName(nodes[parentNodeIdx], nodeIdIds, nodes) + "/" + fullName
		}
	}
	return fullName
}

// 并发安全缓存
var enumOptionsCache = sync.Map{}

// 获取构建器枚举类型所有可选值
func GetEnumOptions[T comparable](e enum.EnumInterface[T]) []builderdto.Option {
	if val, ok := enumOptionsCache.Load(e); ok {
		return val.([]builderdto.Option)
	}
	sortConsts := e.GetSortConsts()
	allConstAttrs := e.AllConstAttrs()
	options := make([]builderdto.Option, 0, len(allConstAttrs))

	for _, enumValue := range sortConsts {
		option := builderdto.Option{
			Value: enumValue,
			Label: allConstAttrs[enumValue]["desc"].(string),
		}
		options = append(options, option)
	}

	enumOptionsCache.Store(e, options)
	return options
}

// 并发安全缓存
var enumSelectOptionsCache = sync.Map{}
var enumSelectOptionsIncludeAllCache = sync.Map{}

// 获取构建器选择类型类型所有可选值
func GetEnumSelectOptions[T comparable](e enum.EnumInterface[T], includeAll ...bool) (options []builderdto.Option) {
	if len(includeAll) > 0 && includeAll[0] {
		if val, ok := enumSelectOptionsIncludeAllCache.Load(e); ok {
			return val.([]builderdto.Option)
		}
		options = append([]builderdto.Option{{Value: consts.ALL_SELECT_VALUE, Label: "全部"}}, GetEnumOptions(e)...)
		enumSelectOptionsIncludeAllCache.Store(e, options)
	} else {
		if val, ok := enumSelectOptionsCache.Load(e); ok {
			return val.([]builderdto.Option)
		}
		options = GetEnumOptions(e)
		enumSelectOptionsCache.Store(e, options)
	}
	return
}

// 并发安全缓存
var enumTableColOptionsCache = sync.Map{}

// 获取表格表头枚举类型所有可选值
func GetEnumTableColOptions[T comparable](e enum.EnumInterface[T]) []builderdto.TableColOption {
	if val, ok := enumTableColOptionsCache.Load(e); ok {
		return val.([]builderdto.TableColOption)
	}

	sortConsts := e.GetSortConsts()
	allConstAttrs := e.AllConstAttrs()
	options := make([]builderdto.TableColOption, 0, len(allConstAttrs))

	for _, enumValue := range sortConsts {
		option := builderdto.TableColOption{
			Value: enumValue,
			Label: allConstAttrs[enumValue]["desc"].(string),
		}
		if bgColor, ok := allConstAttrs[enumValue]["color"]; ok {
			option.BgColor = bgColor.(string)
		}
		options = append(options, option)
	}

	enumTableColOptionsCache.Store(e, options)
	return options
}

// 并发安全缓存
var enumTableStateCache = sync.Map{}
var enumTableStateIncludeAllCache = sync.Map{}

// 获取表格状态栏所有可选值
func GetEnumTableState[T comparable](e enum.EnumInterface[T], includeAll ...bool) (options []builderdto.TableState) {
	if len(includeAll) > 0 && includeAll[0] {
		if val, ok := enumTableStateIncludeAllCache.Load(e); ok {
			return val.([]builderdto.TableState)
		}
		sortConsts := e.GetSortConsts()
		allConstAttrs := e.AllConstAttrs()
		options = make([]builderdto.TableState, 0, len(allConstAttrs)+1)
		options = append(options, builderdto.TableState{Code: consts.ALL_SELECT_VALUE, Title: "全部"})
		for _, enumValue := range sortConsts {
			option := builderdto.TableState{
				Code:  enumValue,
				Title: allConstAttrs[enumValue]["desc"].(string),
			}
			options = append(options, option)
		}
		enumTableStateIncludeAllCache.Store(e, options)
	} else {
		if val, ok := enumTableStateCache.Load(e); ok {
			return val.([]builderdto.TableState)
		}
		sortConsts := e.GetSortConsts()
		allConstAttrs := e.AllConstAttrs()
		options = make([]builderdto.TableState, 0, len(allConstAttrs))
		for _, enumValue := range sortConsts {
			option := builderdto.TableState{
				Code:  enumValue,
				Title: allConstAttrs[enumValue]["desc"].(string),
			}
			options = append(options, option)
		}
		enumTableStateCache.Store(e, options)
	}
	return options
}
